"""
Copyright (c) 2022 Huawei Technologies Co.,Ltd.

openGauss is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:

          http://license.coscl.org.cn/MulanPSL2

THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
"""
"""
Case Type   : 资源池化
Case Name   : 资源池化场景下, 无任何业务压力, 进行failover操作
Create At   : 2024-04-07
Owner       : songshixuan
Description :
    1、查看集群状态 cm_ctl query -Cv
    2、构建failover操作,再次查看切换后集群状态 cm_ctl query -Cv
    3、重新启动原主节点,再次查看集群状态 cm_ctl query -Cv
    4、抓一下异常堆栈信息
    5、恢复集群原始状态
Expect      :
    1、集群状态正常，数据库节点状态正常
    2、构建failover操作成功，切换后集群状态正常，备节点上升为新主节点，原主节点stop
    3、重启原主节点成功，集群状态正常
    4、抓取堆栈信息成功
    5、恢复集群原始状态成功,集群状态正常
History     :
    1、2024-04-07 创建
    2、2025-07-10 改造用例为1p1s环境可执行
"""

import os
import unittest
import time

from testcase.utils.CommonSH import CommonSH
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger
from yat.test import macro

Primary_SH = CommonSH('PrimaryDbUser')
Standby1_SH = CommonSH('Standby1DbUser')

@unittest.skipIf(1 == Primary_SH.get_node_num(), '单机环境不执行')
class SharedStorage(unittest.TestCase):

    def setUp(self):
        self.log = Logger()
        self.log.info(f'-----{os.path.basename(__file__)} start-----')
        self.constant = Constant()
        self.s1_comsh = CommonSH('Standby1DbUser')

    def test_shared_storage(self):
        text = '-----step1:查看集群状态; expect:集群状态正常-----'
        self.log.info(text)

        status = Primary_SH.exec_cm_ctl(mode='query', param='-Cv')
        self.log.info(status)
        self.assertIn('cluster_state   : Normal', status, '执行失败' + text)

        text = '-----step2:原主节点构建; expect:停止成功，主节点进入Manually stopped状态-----'
        self.log.info(text)
        # 运行failover脚本进行failover构建
        stopdn = Primary_SH.exec_failover()
        self.log.info(stopdn)
        time.sleep(50)
        status = Primary_SH.exec_cm_ctl(mode='query', param='-Cv')
        self.log.info(status)
        res1 = status.splitlines()[-1].split('|')[0].split('6001')[-1]
        res2 = status.splitlines()[-1].split('|')[1].split('6002')[-1]
        self.log.info(res1)
        self.log.info(res2)
        self.assertIn('P Down    Manually stopped', res1, '执行失败' + text)
        self.assertIn('S Primary Normal', res2, '执行失败' + text)

        text = '-----step3:原主节点进行节点启动; expect:执行成功-----'
        self.log.info(text)
        startdn = Primary_SH.exec_cm_ctl('start')
        self.log.info(startdn)
        self.assertIn(self.constant.cm_start_success_msg, startdn,
                '拉起dn节点失败')
        status = Primary_SH.exec_cm_ctl(mode='query', param='-Cv')
        self.log.info(status)
        self.assertIn('cluster_state   : Normal', status, '执行失败' + text)
        res1 = status.splitlines()[-1].split('|')[0].split('6001')[-1]
        self.log.info(res1)
        self.assertIn('P Standby Normal', res1, '执行失败' + text)

    def tearDown(self):
        text = '-----step4:抓一下standby1异常堆栈; expect:成功-----'
        self.log.info(text)
        # 2024-6-3 新增gstack抓取功能，当检测到异常的时候先粗暴的抓一下堆栈
        queryCmd = Standby1_SH.exec_cmd_under_user("ps -ux | grep app/bin/gaussdb | grep -v -- '--color'")
        pid = queryCmd.split()[1]
        gsStackGaussdb = Standby1_SH.exec_cmd_under_user("gstack " + pid)
        self.log.info(gsStackGaussdb)
        queryCmd = Standby1_SH.exec_cmd_under_user("ps -ux | grep app/bin/dssserver | grep -v -- '--color'")
        pid = queryCmd.split()[1]
        gsStackDssServer = Standby1_SH.exec_cmd_under_user("gstack " + pid)
        self.log.info(gsStackDssServer)

        text = '-----step5:恢复环境为初始集群状态; expect:成功-----'
        self.log.info(text)
        status = Primary_SH.exec_cm_ctl(mode='query', param='-Cv')
        self.log.info(status)
        status = Primary_SH.check_cluster_core_status(status, wait_times=600)
        self.log.info(status)

        recovery = Primary_SH.exec_cm_ctl(mode='switchover', param='-a')
        self.log.info(recovery)
        self.assertIn(self.constant.cm_switchover_success_msg, recovery,
                      '执行失败' + text)

        status = Primary_SH.exec_cm_ctl(mode='query', param='-Cv')
        self.log.info(status)
        self.assertIn('P Primary Normal',
                      status.splitlines()[-1].split('|')[0].split('6001')[-1],
                      '执行失败' + text)
        self.assertIn('S Standby Normal',
                      status.splitlines()[-1].split('|')[1].split('6002')[-1],
                      '执行失败' + text)
        self.log.info(f'-----{os.path.basename(__file__)} end-----')
